package com.jianbing.mongo;

import com.mongodb.*;
import com.mongodb.client.MongoDatabase;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;

/**
 * \* Created with IntelliJ IDEA. \* User: LFL \* Date: 2017/4/24 \* Time: 14:52
 * \* To change this template use File | Settings | File Templates. \*
 * Description: \
 */
@Repository
public class MongoConnections {
	private static Logger log = Logger.getLogger(MongoConnections.class);

	private static String mongoDB_server1;

	private static String mongoDB_port1;

	private static String mongoDB_server2;

	private static String mongoDB_port2;

	private static String mongoDB_username;

	private static String mongoDB_password;

	private static String mongoDB_DEFAULT_DB;

	private static String mongoDB_ReplSetName;

	@Value("#{propertiesReader['mongoDB_server1']}")
	public void setMongoDB_server1(String mongoDB_server1) {
		MongoConnections.mongoDB_server1 = mongoDB_server1;
	}

	@Value("#{propertiesReader['mongoDB_port1']}")
	public void setMongoDB_port1(String mongoDB_port1) {
		MongoConnections.mongoDB_port1 = mongoDB_port1;
	}
	
	@Value("#{propertiesReader['mongoDB_server2']}")
	public void setMongoDB_server2(String mongoDB_server2) {
		MongoConnections.mongoDB_server2 = mongoDB_server2;
	}

	@Value("#{propertiesReader['mongoDB_port2']}")
	public void setMongoDB_port2(String mongoDB_port2) {
		MongoConnections.mongoDB_port2 = mongoDB_port2;
	}

	@Value("#{propertiesReader['mongoDB_username']}")
	public void setMongoDB_username(String mongoDB_username) {
		MongoConnections.mongoDB_username = mongoDB_username;
	}

	@Value("#{propertiesReader['mongoDB_password']}")
	public void setMongoDB_password(String mongoDB_password) {
		MongoConnections.mongoDB_password = mongoDB_password;
	}

	@Value("#{propertiesReader['mongoDB_DEFAULT_DB']}")
	public void setMongoDB_DEFAULT_DB(String mongoDB_DEFAULT_DB) {
		MongoConnections.mongoDB_DEFAULT_DB = mongoDB_DEFAULT_DB;
	}

	@Value("#{propertiesReader['mongoDB_ReplSetName']}")
	public void setMongoDB_ReplSetName(String mongoDB_ReplSetName) {
		MongoConnections.mongoDB_ReplSetName = mongoDB_ReplSetName;
	}

	private static MongoClient mongoClient = null;

	private static MongoClient createMongoDBClient() {
		// 构建Seed列表
		List<ServerAddress> seedList = new ArrayList<ServerAddress>();
		ServerAddress seed1 = new ServerAddress(mongoDB_server1, Integer.valueOf(mongoDB_port1));
		ServerAddress seed2 = new ServerAddress(mongoDB_server2, Integer.valueOf(mongoDB_port2));
		seedList.add(seed1);
		seedList.add(seed2);

		// 构建鉴权信息
		List<MongoCredential> credentials = new ArrayList<MongoCredential>();
		credentials.add(MongoCredential.createScramSha1Credential(mongoDB_username, mongoDB_DEFAULT_DB,
				mongoDB_password.toCharArray()));

		// 构建操作选项，requiredReplicaSetName属性外的选项根据自己的实际需求配置，默认参数满足大多数场景
		MongoClientOptions options = MongoClientOptions.builder().requiredReplicaSetName(mongoDB_ReplSetName)
				.socketKeepAlive(true).connectionsPerHost(50).minConnectionsPerHost(3)
				.threadsAllowedToBlockForConnectionMultiplier(1000000).socketTimeout(0).maxWaitTime(1000 * 60 * 200)
				.serverSelectionTimeout(1000 * 60 * 200).connectTimeout(1000 * 60 * 20).maxConnectionIdleTime(0)
				.maxConnectionLifeTime(0).build();
		return new MongoClient(seedList, credentials, options);
	}

	public static MongoClient createMongoDBClientWithURI() {
		// 另一种通过URI初始化
		// mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]
		ServerAddress seed1 = new ServerAddress(mongoDB_server1, Integer.valueOf(mongoDB_port1));
		ServerAddress seed2 = new ServerAddress(mongoDB_server2, Integer.valueOf(mongoDB_port2));
		List<ServerAddress> seedList = new ArrayList<ServerAddress>();
		seedList.add(seed1);
		seedList.add(seed2);
		MongoClientURI connectionString = new MongoClientURI("mongodb://" + mongoDB_username + ":" + mongoDB_password
				+ "@" + seedList + "/" + mongoDB_DEFAULT_DB + "?replicaSet=" + mongoDB_ReplSetName);
		return new MongoClient(connectionString);
	}

	private static MongoClient initMongoClient() {
		MongoClient mongoClient = null;
		try {
			// 连接到 mongodb 服务
			if (mongoDB_server1.equals("localhost")) {
				MongoClientOptions options = MongoClientOptions.builder().socketKeepAlive(true).connectionsPerHost(60)
						.minConnectionsPerHost(10).threadsAllowedToBlockForConnectionMultiplier(1000000)
						.socketTimeout(0).maxWaitTime(1000 * 60 * 200).serverSelectionTimeout(1000 * 60 * 200)
						.connectTimeout(1000 * 60 * 20).maxConnectionIdleTime(0).maxConnectionLifeTime(0).build();
				ServerAddress dbAddress = new ServerAddress(mongoDB_server1, Integer.valueOf(mongoDB_port1));
				mongoClient = new MongoClient(dbAddress, options); // for local
																	// mongodb
			} else {
				mongoClient = createMongoDBClient();
			}
			return mongoClient;
		} catch (Exception e) {
			log.error(e.toString(), e);
		}
		return null;
	}

	public static MongoClient getMongoClient() {
		if (mongoClient == null) {
			synchronized (MongoConnections.class) {
				if (mongoClient == null) {
					mongoClient = initMongoClient();
				}
			}
		}
		return mongoClient;
	}

	public static MongoDatabase getDatabase(String databaseName) {
		try {
			if (mongoClient == null) {
				synchronized (MongoConnections.class) {
					if (mongoClient == null) {
						mongoClient = initMongoClient();
					}
				}
			}

			MongoDatabase mongoDatabase = mongoClient.getDatabase(databaseName);
			return mongoDatabase;

		} catch (Exception e) {
			log.error("getDatabase error");
			log.error(e.toString(), e);
		}
		return null;
	}
}
